/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ruoyi.common.utils.equipment;

/**
 *
 * @author Administrator
 */
public class RC4 {

    /**
     * RC4 加解密
     * @param data
     * @param key
     * @return
     */
    public static String encry_decry_RC4(String data, String key) {
        if (data == null || key == null) {
            return null;
        }
        byte b_data[] = HEXUtil.HexToByte(data);
        byte b_Key[] = HEXUtil.HexToByte(key);
        byte b_Result[] =  RC4Base(b_data,b_Key);
        return HEXUtil.ByteToHex(b_Result);
    }

    /**
     * RC4 加解密
     * @param data
     * @param key
     * @return
     */
    public static byte[] encry_decry_RC4(byte data[], byte key[]) {
        if (data == null || key == null) {
            return null;
        }
        return RC4Base(data,key);
    }

    /**
     * 初始化RC4的密钥序列
     *
     * @param b_key RC4的密钥
     * @return
     */
    private static short[] initKey(byte[] b_key) {
        short S[] = new short[256];

        for (int i = 0; i < 256; i++) {
            S[i] = (short) i;
        }
        int index1 = 0;
        int index2 = 0;

        if (b_key == null || b_key.length == 0) {
            return null;
        }
        short key_len = (short) b_key.length;
        short tmp;

        for (int i = 0; i < 256; i++) {
            index2 = (index2 + S[i] + ubyte(b_key[i % key_len])) % 256;
            tmp = S[index2];
            S[index2] = S[i];
            S[i] = tmp;
        }
        return S;
    }

    /**
     * 返回无符号的整形值
     *
     * @param b
     * @return
     */
    private static short ubyte(byte b) {
        return (short)(b & 0x00ff);
    }

    /**
     * RC4 加解密
     *
     * @param input 需要加密/解密的数据
     * @param mKkey RC4的密钥
     * @return 解密/加密 后的数据
     */
    private static byte[] RC4Base(byte[] input, byte[] mKkey) {
        int i = 0;
        int j = 0;
        short S[] = initKey(mKkey);
        int counter = 0;
        short temp = 0;
        int data_len = input.length;
        short PRGA = 0;

        byte[] result = new byte[data_len];
        int VECTOR_LENGTH = 256;
        for (counter = 0; counter < data_len; counter++) {
            i = (i + 1) % VECTOR_LENGTH;
            j = (j + S[i]) % VECTOR_LENGTH;
            temp = S[i];
            S[i] = S[j];
            S[j] = temp;

            PRGA = S[(S[i] + S[j]) % VECTOR_LENGTH];

            result[counter] = (byte) (PRGA ^ ubyte(input[counter]));
        }
        return result;
    }
}
